package JUC.第04章_锁;


import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class B2_可重入锁2 {
    public static void main(String[] args) {

        //synchronized和ReentrantLock  可重入锁又名递归锁
        //线程可以获得自己线程
        Lock lock = new ReentrantLock();//默认 非公平锁 synchronized也是非公平锁
        Lock lock0 = new ReentrantLock(false);//非公平锁  上来先尝试占有锁 如果尝试失败   就开始采取公平锁类似的方式
        Lock lock1 = new ReentrantLock(true);
        //公平锁  每个线程先查看等待队列，如果为空或者是等待队列的第一个，就占有所，否则就会加入等待队列中  进行FIFO规则

        /**
         *   线程在外层方法获取锁的时候
         *   在进入内层方法会自动获取锁
         *
         *   线程可以进入任何一个它已经拥有的锁
         *   所同步着的代码块
         */
        Phone phone = new Phone();
//        new Thread(phone::m1,"t1").start();
//        new Thread(phone::m2,"t2").start();
        new Thread(phone,"t3").start();
        new Thread(phone,"t4").start();

    }

}
class Phone implements Runnable {
    //锁的是资源类方法
    public synchronized void m1() {
        System.out.println(Thread.currentThread().getId()+ "\t" + Thread.currentThread().getName()+"****外");
        try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace(); }
        m2();//当有线程获得m1时   他会同时获得m2的锁  即m2也被锁住了  其他不可调用
    }
    public synchronized void m2(){
        System.out.println(Thread.currentThread().getId()+"\t" +Thread.currentThread().getName()+"****内");
    }

    Lock lock=new ReentrantLock();
    @Override
    public void run(){
        get();
    }

    public void get(){
        /**
         * 线程可以进入任何一个它已经拥有的锁
         * 所同步着的代码块
         */
        //lock.lock();
        lock.lock();  //可以加锁可多次  但是也要解锁几次
        try {
            System.out.println(Thread.currentThread().getId()+"\t"+Thread.currentThread().getName()+"****lock外外外");
            set();
        }finally {
            //lock.unlock();
            lock.unlock();
        }
    }
    public void set(){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getId()+"\t"+Thread.currentThread().getName()+"****lock内内内");
        }finally {
            lock.unlock();
        }
    }

}
